<template>
  <div>
    <FormBuilder />
    <!-- Mount the builder -->

    <el-divider />

    <h1>表单渲染器示例</h1>
    <div v-if="runtimeFormDef">
      <FormRenderer
        :form-def="runtimeFormDef"
        :form-data="sampleData"
        ref="formRendererInstance"
      />
      <el-button
        @click="submitRenderedForm"
        type="primary"
        style="margin-top: 20px"
        >提交渲染的表单</el-button
      >
      <el-button @click="loadDefForRuntime"
        >加载设计器中的定义到渲染器</el-button
      >
      <pre>{{ submittedData }}</pre>
    </div>
    <div v-else>
      <p>
        请先在设计器中设计表单并保存/加载，或点击“加载设计器中的定义到渲染器”按钮（若设计器有内容）。
      </p>
      <el-button @click="loadDefForRuntime"
        >加载设计器中的定义到渲染器</el-button
      >
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import FormBuilder from '@/components/form-builder/FormBuilder.vue'; // Adjust path if needed
import FormRenderer from '@/components/form-renderer/FormRenderer.vue'; // Adjust path
import { FormDefinition } from '@/models/form.model'; // Adjust path
import { ElMessage } from 'element-plus';

const runtimeFormDef = ref<FormDefinition | null>(null);
const sampleData = ref<any>(null); // Initialize with null or appropriate structure
const submittedData = ref<any>(null);
const formRendererInstance = ref<InstanceType<typeof FormRenderer> | null>(
  null
);

function loadDefForRuntime() {
  const storedJson = localStorage.getItem('formBuilderDefinition');
  if (storedJson) {
    try {
      runtimeFormDef.value = FormDefinition.fromJson(storedJson);
      prepareSampleData(); // Prepare sample data based on the loaded definition
      ElMessage.success('定义已加载到渲染器');
    } catch (e) {
      console.error('Error loading definition for runtime:', e);
      ElMessage.error('加载定义失败');
      runtimeFormDef.value = null;
    }
  } else {
    ElMessage.warning('LocalStorage中没有找到 "formBuilderDefinition"');
    runtimeFormDef.value = null;
  }
}

function prepareSampleData() {
  if (!runtimeFormDef.value || !runtimeFormDef.value.dataMetaModel) {
    sampleData.value = runtimeFormDef.value?.dataMetaModel?.isCollection
      ? []
      : {};
    return;
  }

  const meta = runtimeFormDef.value.dataMetaModel;
  if (meta.isCollection) {
    // Create a couple of sample items for collection
    sampleData.value = [
      createEmptyDataItem(meta.fields),
      createEmptyDataItem(meta.fields),
    ];
  } else {
    sampleData.value = createEmptyDataItem(meta.fields);
  }
}

function createEmptyDataItem(
  fields: Array<{ field: string; name: string; type?: string }>
): Record<string, any> {
  const item: Record<string, any> = {};
  // Find all input props defined in the grid
  const inputProps = new Set<string>();
  if (runtimeFormDef.value) {
    runtimeFormDef.value.gridDefinition.cells.forEach((cell) => {
      if (cell.content?.type === 'input') {
        const prop = (cell.content as any).prop;
        if (prop) inputProps.add(prop);
      }
    });
  }

  // Initialize properties for all defined input props
  inputProps.forEach((prop) => {
    // You could check fields from meta.fields to set more specific defaults based on type
    const fieldDef = fields.find((f) => f.field === prop);
    if (fieldDef?.type === 'number')
      item[prop] = undefined; // Or 0 if appropriate
    else if (fieldDef?.type === 'boolean') item[prop] = false;
    else item[prop] = ''; // Default for text etc.
  });

  return item;
}

async function submitRenderedForm() {
  if (formRendererInstance.value) {
    const isValid = await formRendererInstance.value.validateForm();
    if (isValid) {
      submittedData.value = formRendererInstance.value.getFormData();
      console.log('Form Submitted:', submittedData.value);
      ElMessage.success('表单数据已提交 (见控制台和页面)');
    } else {
      console.log('Form validation failed');
      ElMessage.error('表单校验失败!');
      submittedData.value = null;
    }
  }
}

onMounted(() => {
  // Optionally load a default definition or previously saved one
  loadDefForRuntime();
});
</script>

<style>
/* Add some global styles if needed, or scoped within components */
</style>
